package blackstar.plugin.performance.stat;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author RayWoo (ayufox@gmail.com)
 * 
 */
public class SimpleStater
{
	private final static Log LOGGER = LogFactory.getLog(SimpleStater.class);

	private ThreadHoldConfig threadHoldConfig;
	private Map<String, SimpleStatItem> stats = new HashMap<String, SimpleStatItem>();

	public SimpleStater(ThreadHoldConfig threadHoldConfig)
	{
		super();
		this.threadHoldConfig = threadHoldConfig;
	}

	public void add(File file) throws IOException
	{
		InputStream is = new FileInputStream(file);
		try
		{
			add(is);
		} finally
		{
			is.close();
		}
	}

	private void add(InputStream inputStream) throws IOException
	{
		add(new InputStreamReader(inputStream));
	}

	private void add(Reader reader) throws IOException
	{
		BufferedReader br = new BufferedReader(reader);
		String line = null;
		String[] datas = null;
		String className = null;
		String methodName = null;
		long timeNano = 0;

		int success = 0;
		int ignore = 0;
		while ((line = br.readLine()) != null)
		{
			datas = line.split("\\|");
			// 数据格式是className|methodName|timeNano[|timestamp]，其中timestamp部分是可选的
			if (datas.length >= 3)
			{
				try
				{
					className = datas[0];
					methodName = datas[1];
					timeNano = Long.parseLong(datas[2]);
					add(className, methodName, timeNano);
					success++;
				} catch (Exception e)
				{
					LOGGER.error("error when handle data[" + line + "]", e);
					ignore++;
				}
			} else
			{
				LOGGER.error("ignore handle data[" + line + "]");
				ignore++;
			}
		}

		LOGGER.info("handle reader[" + reader + "] success[" + success
				+ "]  ignore [" + ignore + "]");
	}

	public void add(String className, String methodName, long timeNano)
	{
		if (timeNano > 0)
		{
			String fullName = className + "." + methodName;
			SimpleStatItem item = this.stats.get(fullName);
			if (item == null)
			{
				item = new SimpleStatItem(className, methodName, this.threadHoldConfig);
				this.stats.put(fullName, item);
			}
			item.add(timeNano);
		}
	}

	public void genToFile(File file) throws IOException
	{
		if (file.exists())
		{
			file.delete();
		}

		File dir = file.getParentFile();
		if (!dir.exists())
		{
			dir.mkdirs();
		}

		FileWriter fileWriter = new FileWriter(file);

		try
		{
			BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
			bufferedWriter.write("ClassName|MethodName|TotalInvokes|TotalTimeNano");
			long[] threadholdsMS = this.threadHoldConfig.getThreadholdsInMS();
			for (int i=0; i<threadholdsMS.length; i++)
			{
				bufferedWriter.write("|<" + threadholdsMS[i]);
			}
			bufferedWriter.write("|>=" + threadholdsMS[threadholdsMS.length-1] + "\n");
			
			for (SimpleStatItem item : stats.values())
			{
				bufferedWriter.write(item.getClassName() + "|"
						+ item.getMethodName() + "|" + item.getTotalInvokes()
						+ "|" + item.getTotalTimeNano());
				long[] threadholdCounts = item.getThreadholdCounts();
				for (int i=0; i<threadholdCounts.length; i++)
				{
					bufferedWriter.write("|" + threadholdCounts[i]);
				}
				bufferedWriter.write("\n");
			}
			bufferedWriter.flush();
		} finally
		{
			fileWriter.close();
		}
	}
}